package com.bii.gelapp;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Hashtable;

import org.opencv.android.Utils;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Bitmap.Config;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

public class AutoActivity extends Activity {
	// settings
	Settings slsettings;
	String analysisorigin = "";

	// pic attributes
	Button btPrev, btCompare;
	ImageView ivImage;

	Bitmap originalBmp;
	Bitmap colorBmp;
	Bitmap activeBmp;

	Mat srcImg;
	Bitmap myBitmap32;

	// gaussian
	int gaussianprogress;

	// gabor
	int kernelSize = 24;
	double sigma = 0;
	double theta = Math.PI / 2;
	double lambda = 0;
	double gamma = 1;
	double psi = 1.5;
	int inverse;
	int thresholdvalue;
	

	// segmentation
	ArrayList<ConnectedComponent> connectedComponentList = new ArrayList<ConnectedComponent>();
	ArrayList<ConnectedComponent> componentlist = new ArrayList<ConnectedComponent>();
	ArrayList<ConnectedComponent> markerlist = new ArrayList<ConnectedComponent>();
	int minsize;
	Mat destImg;
	Bitmap grayBmp;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.autoactivity);

		if (getIntent().hasExtra("analysisorigin")) {
			analysisorigin = getIntent().getStringExtra("analysisorigin");
		}

		slsettings = RotationActivity.settings;
		ivImage = (ImageView) findViewById(R.id.ivImage);
		activeBmp = null;
		originalBmp = null;
		colorBmp = null;
		try {
			originalBmp = InternalStorage.readBitmap(this, "rotatedBmp");
			activeBmp = InternalStorage.readBitmap(this, "rotatedBmp");
			colorBmp = InternalStorage.readBitmap(this, "rotatedBmp");
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		// gaussian
		gaussianprogress = slsettings.gaussianprogress;
		gaussianprogress = slsettings.gaussianprogress;
		int gaussiansigma = gaussianprogress;
		int gaussiansigma2 = gaussianprogress;
		if (gaussianprogress != 0) {
			srcImg = new Mat(originalBmp.getHeight(), originalBmp.getWidth(),
					CvType.CV_8U, new Scalar(4));
			myBitmap32 = originalBmp.copy(Bitmap.Config.ARGB_8888, true);
			Utils.bitmapToMat(myBitmap32, srcImg);

			Mat noiseFilteredImg = new Mat();
			Imgproc.GaussianBlur(srcImg, noiseFilteredImg, new Size(9, 9),
					gaussiansigma, gaussiansigma2);
			Bitmap gaussianBlurredBmp = Bitmap.createBitmap(
					noiseFilteredImg.cols(), noiseFilteredImg.rows(),
					Bitmap.Config.RGB_565);
			Utils.matToBitmap(noiseFilteredImg, gaussianBlurredBmp);
			activeBmp = gaussianBlurredBmp;
			originalBmp = gaussianBlurredBmp;

		} else {

			activeBmp = originalBmp;
		}

		// ivImage.setImageBitmap(activeBmp);
		// gabor
		sigma = slsettings.sigma;
		lambda = slsettings.lambda;
		thresholdvalue = slsettings.thresholdprogress;
		inverse = slsettings.inverse;

		Mat filtermat = new Mat(originalBmp.getHeight(),
				originalBmp.getWidth(), CvType.CV_8U);
		Utils.bitmapToMat(originalBmp, filtermat);
		Imgproc.cvtColor(filtermat, filtermat, Imgproc.COLOR_BGR2GRAY);
		Mat resultImg = new Mat();
		Mat gaborKernel = Imgproc.getGaborKernel(new Size(kernelSize,
				kernelSize), sigma, theta/* horizontal */, lambda, gamma, psi,
				CvType.CV_32F);
		Imgproc.filter2D(filtermat, resultImg, -1, gaborKernel);
		Bitmap filteredBmp = Bitmap.createBitmap(resultImg.cols(),
				resultImg.rows(), Bitmap.Config.ARGB_8888);
		Utils.matToBitmap(resultImg, filteredBmp);
		Bitmap gaborBmp = filteredBmp;
		activeBmp = filteredBmp;
		Bitmap takenBmp = gaborBmp;
		Mat srcImg = new Mat(takenBmp.getHeight(), takenBmp.getWidth(),
				CvType.CV_8U, new Scalar(4));
		Bitmap myBitmap32 = takenBmp.copy(Bitmap.Config.ARGB_8888, true);
		Utils.bitmapToMat(myBitmap32, srcImg);
		Imgproc.cvtColor(srcImg, srcImg, Imgproc.COLOR_BGR2GRAY);
		Mat thresholdMat = new Mat(takenBmp.getHeight(), takenBmp.getWidth(),
				CvType.CV_8U, new Scalar(4));
		/*
		 * if (inverse == 1) { Imgproc.dilate(srcImg, srcImg,
		 * Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(2, 2)));
		 * Imgproc.threshold(srcImg, thresholdMat, thresholdvalue, 255,
		 * Imgproc.THRESH_BINARY_INV); } else { Imgproc.dilate(srcImg, srcImg,
		 * Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(2, 2)));
		 * Imgproc.threshold(srcImg, thresholdMat, thresholdvalue, 255,
		 * Imgproc.THRESH_BINARY); }
		 */
		Imgproc.dilate(srcImg, srcImg, Imgproc.getStructuringElement(
				Imgproc.MORPH_RECT, new Size(2, 2)));
		Imgproc.threshold(srcImg, thresholdMat, thresholdvalue, 255,
				Imgproc.THRESH_BINARY);

		if (inverse == 1) {
			Imgproc.dilate(thresholdMat, thresholdMat, Imgproc
					.getStructuringElement(Imgproc.MORPH_RECT, new Size(2, 2)));
			Imgproc.threshold(thresholdMat, thresholdMat, thresholdvalue, 255,
					Imgproc.THRESH_BINARY_INV);
		} else {
			Imgproc.dilate(srcImg, srcImg, Imgproc.getStructuringElement(
					Imgproc.MORPH_RECT, new Size(2, 2)));
			Imgproc.threshold(srcImg, thresholdMat, thresholdvalue, 255,
					Imgproc.THRESH_BINARY);
		}
		Bitmap thBmp = Bitmap.createBitmap(thresholdMat.cols(),
				thresholdMat.rows(), Bitmap.Config.ARGB_8888);
		Utils.matToBitmap(thresholdMat, thBmp);

		activeBmp = thBmp;
		originalBmp = thBmp;
		ivImage.setImageBitmap(originalBmp);
		
		/*
		// segmentation
		minsize = slsettings.segmentationminsize;
		takenBmp = originalBmp;
		srcImg = new Mat(takenBmp.getHeight(), takenBmp.getWidth(),
				CvType.CV_8U, new Scalar(4));
		Utils.bitmapToMat(takenBmp, srcImg);
		findConnectedComponents(srcImg, destImg, connectedComponentList,
				minsize);
		//test here
		drawRectangles();
		Bitmap segmentedBmp = Bitmap.createBitmap(destImg.cols(),
				destImg.rows(), Bitmap.Config.RGB_565);
		Utils.matToBitmap(destImg, segmentedBmp);
		ivImage.setImageBitmap(segmentedBmp);
		*/
		//segmentation
		minsize = slsettings.segmentationminsize;
		takenBmp = originalBmp;
		Utils.bitmapToMat(takenBmp, srcImg);
		Imgproc.cvtColor(srcImg, srcImg, Imgproc.COLOR_BGR2GRAY);
		ArrayList<ConnectedComponent> connectedComponentList = new ArrayList<ConnectedComponent>();
		destImg = new Mat();
		Imgproc.cvtColor(srcImg, destImg, Imgproc.COLOR_GRAY2BGR);
		findConnectedComponents(srcImg, destImg,
				connectedComponentList, minsize);
		
		Collections.sort(componentlist,
				new Comparator<ConnectedComponent>() {
					@Override
					public int compare(ConnectedComponent cc1,
							ConnectedComponent cc2) {
						return cc1.left - cc2.left;
					}
				});
		
		//grey scale 
		grayBmp = RotationActivity.colorBmp.copy(Config.ARGB_8888,
				true);
		srcImg = new Mat(grayBmp.getHeight(), grayBmp.getWidth(),
				CvType.CV_8U, new Scalar(4));
		myBitmap32 = grayBmp.copy(Bitmap.Config.ARGB_8888,
				true);
		Utils.bitmapToMat(myBitmap32, srcImg);
		Imgproc.cvtColor(srcImg, destImg, Imgproc.COLOR_BGR2GRAY);
		Utils.matToBitmap(destImg, grayBmp);
		fixRectangles();
		MarkerStandard ms = StartActivity.ms;
		ArrayList<ConnectedComponent> componentmarkers = new ArrayList<ConnectedComponent>();

		if (ms.getmarkers().size() < componentlist.size()) {
			for (int i = 0; i < ms.getmarkers().size() + 1; i++) {
				// for (int i = 0; i < 8; i++) {
				componentmarkers.add(componentlist.get(i));
			}

		}
		
		double graphaverage = 9999;
		double thresholdvalue = 30;

		Point pt1 = null;
		Point pt2 = null;

		while (graphaverage > thresholdvalue) {
			graphaverage = 0;
			ConnectedComponent mincc = new ConnectedComponent();
			mincc.top = 9999;

			ConnectedComponent maxcc = new ConnectedComponent();
			maxcc.top = 0;

			for (int i = 0; i < componentmarkers.size(); i++) {
				if (componentmarkers.get(i).top < mincc.top) {
					mincc = componentmarkers.get(i);
				}
				if (componentmarkers.get(i).top > maxcc.top) {
					maxcc = componentmarkers.get(i);
				}
			}

			// formula of line
			double m1 = 0, m2 = 0, m3 = 0, m4 = 0;
			for (int i = 0; i < componentmarkers.size(); i++) {
				double mlx = (componentmarkers.get(i).left + componentmarkers
						.get(i).right) / 2;
				double mly = (componentmarkers.get(i).top + componentmarkers
						.get(i).bottom) / 2;
				m1 += mly * mly;
				m2 += mlx * mly;
				m3 += mly;
				m4 += mlx;
			}

			double XMean = m3 / componentmarkers.size();
			double YMean = m4 / componentmarkers.size();
			double formulaA = (m2 - m3 * YMean) / (m1 - m3 * XMean);
			double formulaB = YMean - formulaA * XMean;

			int firstx = (mincc.left + mincc.right) / 2;
			int firsty = (mincc.top + mincc.bottom) / 2;
			int lastx = (maxcc.left + maxcc.right) / 2;
			int lasty = (maxcc.top + maxcc.bottom) / 2;

			double bestfity1 = firsty;
			double bestfitx1 = formulaA * bestfity1 + formulaB;// (bestfity1
																// -
																// formulaB)
																// /
																// formulaA;
			double bestfity2 = lasty;
			double bestfitx2 = formulaA * bestfity2 + formulaB;// (bestfity2
																// -
																// formulaB)
																// /
																// formulaA;

			pt1 = new Point(bestfitx1, bestfity1);
			pt2 = new Point(bestfitx2, bestfity2);
			for (int i = componentmarkers.size() - 1; i > -1; i--) {

				double jx = (componentmarkers.get(i).left + componentmarkers
						.get(i).right) / 2;
				double jy = (componentmarkers.get(i).top + componentmarkers
						.get(i).bottom) / 2;
				double jbestfitx = formulaA * jy + formulaB;
				;
				double componentaverage = Math.abs(jx - jbestfitx);
				graphaverage += componentaverage;
			}

			if (graphaverage > thresholdvalue) {
				Log.d("tag1",
						"deleted: " + (componentmarkers.size() - 1));
				componentmarkers.remove(componentmarkers.size() - 1);
			}

			Core.line(destImg, pt1, pt2, new Scalar(255, 0, 255), 5);

		}

		for (int i = 0; i < componentmarkers.size(); i++) {

			markerlist.add(componentmarkers.get(i));
		}

		for (int i = markerlist.size() - 1; i >= 0; i--) {
			componentlist.remove(i);
		}
		
		/*
		Bitmap drawnbmp = Bitmap.createBitmap(destImg.cols(),
				destImg.rows(), Bitmap.Config.RGB_565);
		Utils.matToBitmap(destImg, drawnbmp);
		*/
		
		Bitmap segmentedBmp = Bitmap.createBitmap(destImg.cols(),
				destImg.rows(), Bitmap.Config.RGB_565);
		Utils.matToBitmap(destImg, segmentedBmp);
		activeBmp = segmentedBmp;
		grayBmp = RotationActivity.colorBmp
				.copy(Config.ARGB_8888, true);
		Utils.bitmapToMat(grayBmp, destImg);

		drawRectangles();
		Utils.matToBitmap(destImg, segmentedBmp);
		ivImage.setImageBitmap(segmentedBmp);
		
		ivImage.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				Intent goToNextActivity = new Intent(getApplicationContext(),
						FullscreenActivity.class);
				
				byte[] bytes;
				
				bytes = compressImage(originalBmp);
				goToNextActivity.putExtra("BMP", bytes);
				byte[] bytes2;
				bytes2 = compressImage(activeBmp);
				goToNextActivity.putExtra("BMP2", bytes2);

				goToNextActivity.putExtra("componentlist", componentlist);
				Collections.sort(markerlist,
						new Comparator<ConnectedComponent>() {
							@Override
							public int compare(ConnectedComponent cc1,
									ConnectedComponent cc2) {
								return cc1.top - cc2.top;
							}
						});
				goToNextActivity.putExtra("markerlist", markerlist);
				String origin = "Auto";
				goToNextActivity.putExtra("origin", origin);
				goToNextActivity.putExtra("analysisorigin", analysisorigin);
				startActivity(goToNextActivity);
				
			
			}
		});
		
		btPrev = (Button)findViewById(R.id.btPrev);
		btPrev.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Intent gotoPrevActivity = new Intent(AutoActivity.this, RotationActivity.class);
				startActivity(gotoPrevActivity);
			}
		});
		
		btCompare = (Button)findViewById(R.id.btCompare);
		btCompare.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Intent goToNextActivity = new Intent(getApplicationContext(),
						CompareActivity.class);

				goToNextActivity.putExtra("componentlist", componentlist);
				Collections.sort(markerlist,
						new Comparator<ConnectedComponent>() {
							@Override
							public int compare(ConnectedComponent cc1,
									ConnectedComponent cc2) {
								return cc1.top - cc2.top;
							}
						});
				goToNextActivity.putExtra("markerlist", markerlist);
				String origin = "Auto";
				goToNextActivity.putExtra("origin", origin);
				goToNextActivity.putExtra("analysisorigin", analysisorigin);
				startActivity(goToNextActivity);

				
			}
		});
		
	}

	// srcImg MUST be a BINARY image
	public void findConnectedComponents(Mat srcImg, Mat destImg,
			ArrayList<ConnectedComponent> connectedComponentList, int minArea) {
		Hashtable<Integer, ConnectedComponent> conCompHt = new Hashtable<Integer, ConnectedComponent>();// from
																										// label
																										// to
																										// connected
																										// component
		int[][] labelMatrix = new int[srcImg.height()][srcImg.width()]; // all
																		// elements
																		// will
																		// be
																		// initialized
																		// with
																		// 0
		int issuedLabel = 0;

		System.out.println("Start finding connected components...");

		int temp = 0;
		for (int i = 1; i < srcImg.height() - 1; i++) {
			for (int j = 1; j < srcImg.width() - 1; j++) {
				double[] data = srcImg.get(i, j);
				if (data[0] <= 50) { // black pixel
					// if(data[0] > 50){
					if (labelMatrix[i][j - 1] != 0) {// the left neighbour pixel
														// has label (and of
														// course is black
														// pixel)
						labelMatrix[i][j] = labelMatrix[i][j - 1]; // label
																	// pixel
																	// (i,j),
																	// and admit
																	// it to the
																	// left
																	// neighbor
																	// pixel's
																	// connected
																	// component
						// UPDATE THE CONNECTED COMPONENT
						ConnectedComponent conComp = conCompHt
								.get(labelMatrix[i][j - 1]);
						if (conComp == null) {
							System.out.println(i + "\t" + j + "\t"
									+ labelMatrix[i][j]);
							System.out.println(labelMatrix[i][j - 1]);
							/*
							 * for (int g= 12;g<26;g++){ for (int f= 540; f<560;
							 * f++){ System.out.print(srcImg.get(g, f)[0]+"\t");
							 * } System.out.println(); }
							 * 
							 * for (int g= 12;g<26;g++){ for (int f= 540; f<560;
							 * f++){ System.out.print(labelMatrix[g][f]+"\t"); }
							 * System.out.println(); }
							 */
						}
						conComp.noPixels++;
						if (conComp.right < j)
							conComp.right = j;// no need to update the left, top
												// and bottom boundaries of the
												// connected component
						conCompHt.put(labelMatrix[i][j - 1], conComp);

						// MERGING THE CONNECTED COMPONENT WITH ITS NEIGHBOUR
						// CONNECTED COMPONENTS (If existing any)
						ConnectedComponent neighbourConComp;
						if (labelMatrix[i - 1][j - 1] != 0
								&& labelMatrix[i - 1][j - 1] != labelMatrix[i][j - 1]) {
							temp = labelMatrix[i - 1][j - 1];
							for (int e = j - 1; e < srcImg.width(); e++) {// update
																			// the
																			// labels
																			// of
																			// all
																			// pixels
																			// at
																			// the
																			// same
																			// line
																			// and
																			// have
																			// the
																			// same
																			// label
																			// as
																			// pixel
																			// (i-1,j-1)
								if (labelMatrix[i - 1][e] == temp)
									labelMatrix[i - 1][e] = labelMatrix[i][j - 1];
							}
							for (int e = j - 2; e > 0; e--) {// update the
																// labels of all
																// pixels at the
																// same line as
																// pixel (i,j)
																// and have the
																// same label as
																// pixel
																// (i-1,j-1)
								if (labelMatrix[i][e] == temp)
									labelMatrix[i][e] = labelMatrix[i][j - 1];
							}

							neighbourConComp = conCompHt.get(temp);
							conComp.noPixels += neighbourConComp.noPixels;
							if (neighbourConComp.left < conComp.left)
								conComp.left = neighbourConComp.left;
							if (neighbourConComp.right > conComp.right)
								conComp.right = neighbourConComp.right;
							if (neighbourConComp.top < conComp.top)
								conComp.top = neighbourConComp.top;// no need to
																	// update
																	// the
																	// bottom
																	// boundary
							conCompHt.put(labelMatrix[i][j - 1], conComp);
							conCompHt.remove(temp);// delete the neighbour
													// conComp after it is
													// merged
						}
						if (labelMatrix[i - 1][j] != 0
								&& labelMatrix[i - 1][j] != labelMatrix[i][j - 1]) {
							temp = labelMatrix[i - 1][j];
							for (int e = j; e < srcImg.width(); e++) {// update
																		// the
																		// labels
																		// of
																		// all
																		// pixels
																		// at
																		// the
																		// same
																		// line
																		// and
																		// have
																		// the
																		// same
																		// label
																		// as
																		// pixel
																		// (i-1,j)
								if (labelMatrix[i - 1][e] == temp)
									labelMatrix[i - 1][e] = labelMatrix[i][j - 1];
							}
							for (int e = j - 2; e > 0; e--) {// update the
																// labels of all
																// pixels at the
																// same line as
																// pixel (i,j)
																// and have the
																// same label as
																// pixel (i-1,j)
								if (labelMatrix[i][e] == temp)
									labelMatrix[i][e] = labelMatrix[i][j - 1];
							}

							neighbourConComp = conCompHt.get(temp);
							conComp.noPixels += neighbourConComp.noPixels;
							if (neighbourConComp.left < conComp.left)
								conComp.left = neighbourConComp.left;
							if (neighbourConComp.right > conComp.right)
								conComp.right = neighbourConComp.right;
							if (neighbourConComp.top < conComp.top)
								conComp.top = neighbourConComp.top;// no need to
																	// update
																	// the
																	// bottom
																	// boundary
							conCompHt.put(labelMatrix[i][j - 1], conComp);

							conCompHt.remove(temp);// delete the neighbour
													// conComp after it is
													// merged
						}
						// Log.d("tag1", i + " " + j);
						if (labelMatrix[i - 1][j + 1] != 0
								&& labelMatrix[i - 1][j + 1] != labelMatrix[i][j - 1]) {
							temp = labelMatrix[i - 1][j + 1];
							for (int e = j + 1; e < srcImg.width(); e++) {// update
																			// the
																			// labels
																			// of
																			// all
																			// pixels
																			// at
																			// the
																			// same
																			// line
																			// and
																			// have
																			// the
																			// same
																			// label
																			// as
																			// pixel
																			// (i-1,j+1)
								if (labelMatrix[i - 1][e] == temp)
									labelMatrix[i - 1][e] = labelMatrix[i][j - 1];
							}
							for (int e = j - 2; e > 0; e--) {// update the
																// labels of all
																// pixels at the
																// same line as
																// pixel (i,j)
																// and have the
																// same label as
																// pixel
																// (i-1,j+1)
								if (labelMatrix[i][e] == temp)
									labelMatrix[i][e] = labelMatrix[i][j - 1];
							}

							neighbourConComp = conCompHt.get(temp);
							conComp.noPixels += neighbourConComp.noPixels;
							if (neighbourConComp.left < conComp.left)
								conComp.left = neighbourConComp.left;
							if (neighbourConComp.right > conComp.right)
								conComp.right = neighbourConComp.right;
							if (neighbourConComp.top < conComp.top)
								conComp.top = neighbourConComp.top;// no need to
																	// update
																	// the
																	// bottom
																	// boundary
							conCompHt.put(labelMatrix[i][j - 1], conComp);
							conCompHt.remove(temp);// delete the neighbour
													// conComp after it is
													// merged
						}
					} else if (labelMatrix[i - 1][j - 1] != 0) {// the top-left
																// neighbour
																// pixel has
																// label (and of
																// course is
																// black pixel)
						labelMatrix[i][j] = labelMatrix[i - 1][j - 1]; // label
																		// pixel
																		// (i,j),
																		// and
																		// admit
																		// it to
																		// the
																		// top-left
																		// neighbor
																		// pixel's
																		// connected
																		// component
						// UPDATE THE CONNECTED COMPONENT
						ConnectedComponent conComp = conCompHt
								.get(labelMatrix[i - 1][j - 1]);
						conComp.noPixels++;
						if (conComp.right < j)
							conComp.right = j;
						if (conComp.bottom < i)
							conComp.bottom = i;// no need to update the left and
												// top boundaries of the
												// connected component
						conCompHt.put(labelMatrix[i - 1][j - 1], conComp);

						// MERGING THE CONNECTED COMPONENT WITH ITS NEIGHBOUR
						// CONNECTED COMPONENTS (If existing any)
						ConnectedComponent neighbourConComp;
						if (labelMatrix[i - 1][j] != 0
								&& labelMatrix[i - 1][j] != labelMatrix[i - 1][j - 1]) {
							// This will never happen because
							// labelMatrix[i-1][j] must become equal to
							// labelMatrix[i-1][j-1]
							// when line (i-1) was scanned previously
						}
						if (labelMatrix[i - 1][j + 1] != 0
								&& labelMatrix[i - 1][j + 1] != labelMatrix[i - 1][j - 1]) {
							temp = labelMatrix[i - 1][j + 1];
							for (int e = j + 1; e < srcImg.width(); e++) {// update
																			// the
																			// labels
																			// of
																			// all
																			// pixels
																			// at
																			// the
																			// same
																			// line
																			// and
																			// have
																			// the
																			// same
																			// label
																			// as
																			// pixel
																			// (i-1,j+1)
								if (labelMatrix[i - 1][e] == temp)
									labelMatrix[i - 1][e] = labelMatrix[i - 1][j - 1];
							}
							for (int e = j - 2; e > 0; e--) {// update the
																// labels of all
																// pixels at the
																// same line as
																// pixel (i,j)
																// and have the
																// same label as
																// pixel
																// (i-1,j+1)
								if (labelMatrix[i][e] == temp)
									labelMatrix[i][e] = labelMatrix[i - 1][j - 1];
							}

							neighbourConComp = conCompHt.get(temp);
							conComp.noPixels += neighbourConComp.noPixels;
							if (neighbourConComp.left < conComp.left)
								conComp.left = neighbourConComp.left;
							if (neighbourConComp.right > conComp.right)
								conComp.right = neighbourConComp.right;
							if (neighbourConComp.top < conComp.top)
								conComp.top = neighbourConComp.top;// no need to
																	// update
																	// the
																	// bottom
																	// boundary
							conCompHt.put(labelMatrix[i][j - 1], conComp);
							conCompHt.remove(temp);// delete the neighbour
													// conComp after it is
													// merged
						}

					} else if (labelMatrix[i - 1][j] != 0) {// the top neighbour
															// pixel has label
															// (and of course is
															// black pixel)
						labelMatrix[i][j] = labelMatrix[i - 1][j]; // label
																	// pixel
																	// (i,j),
																	// and admit
																	// it to the
																	// top
																	// neighbour
																	// pixel's
																	// connected
																	// component
						// UPDATE THE CONNECTED COMPONENT
						ConnectedComponent conComp = conCompHt
								.get(labelMatrix[i - 1][j]);
						conComp.noPixels++;
						if (conComp.bottom < i)
							conComp.bottom = i;// no need to update the left,
												// right and top boundaries of
												// the connected component
						conCompHt.put(labelMatrix[i - 1][j], conComp);

						// MERGING THE CONNECTED COMPONENT WITH ITS NEIGHBOUR
						// CONNECTED COMPONENTS (If existing any)
						// ConnectedComponent neighbourConComp;
						if (labelMatrix[i - 1][j + 1] != 0
								&& labelMatrix[i - 1][j + 1] != labelMatrix[i - 1][j]) {
							// This will never happen because
							// labelMatrix[i-1][j+1] must become equal to
							// labelMatrix[i-1][j]
							// when line (i-1) was scanned previously
						}
					} else if (labelMatrix[i - 1][j + 1] != 0) {// the top-right
																// neighbour
																// pixel has
																// label (and of
																// course is
																// black pixel)
						labelMatrix[i][j] = labelMatrix[i - 1][j + 1]; // label
																		// pixel
																		// (i,j),
																		// and
																		// admit
																		// it to
																		// the
																		// top-right
																		// neighbour
																		// pixel's
																		// connected
																		// component
						// UPDATE THE CONNECTED COMPONENT
						ConnectedComponent conComp = conCompHt
								.get(labelMatrix[i - 1][j + 1]);
						conComp.noPixels++;
						if (conComp.bottom < i)
							conComp.bottom = i;// no need to update the left,
												// right and top boundaries of
												// the connected component
						if (conComp.left > j)
							conComp.left = j;
						conCompHt.put(labelMatrix[i - 1][j + 1], conComp);
					} else {// there is none black pixels among the 4 neighbour
							// pixels of pixel (i,j)
							// CREATE A NEW CONNECTED COMPONENT FOR pixel (i,j)
						issuedLabel++;
						labelMatrix[i][j] = issuedLabel;
						ConnectedComponent conComp = new ConnectedComponent();
						conComp.noPixels = 1;
						conComp.label = issuedLabel;
						conComp.left = conComp.right = j;
						conComp.top = conComp.bottom = i;
						conCompHt.put(labelMatrix[i][j], conComp);
					}
				}// end if (data[0]<=50){ //pixel (i,j) is black
			}// end for j
		}// end for i
		System.out.println("Finnished finding connected components.");

		// LISTING ALL THE CONNECTED COMPONENTS
		Enumeration<Integer> en = conCompHt.keys();
		int label = 0;
		while (en.hasMoreElements()) {
			label = en.nextElement();
			connectedComponentList.add(conCompHt.get(label));
		}
		// update the connectedcomponent to offset the gabor filtering
		for (int i = 0; i < connectedComponentList.size(); i++) {

			ConnectedComponent cc = connectedComponentList.get(i);
			/*
			 * if(GaborActivity2.sigmavalue >= sigmatochange) { //cc.top =
			 * cc.top - 12; //cc.bottom = cc.bottom - 12; cc.top = cc.top;
			 * cc.bottom = cc.bottom; } else { cc.top = cc.top + 12; cc.bottom =
			 * cc.bottom + 12; }
			 */
			// 8/9
			// cc.top = cc.top + 8;
			// cc.bottom = cc.bottom +8;

		}

		// DRAW ALL THE CONNECTED COMPONENTS TO destImg (using rectangle bounds)
		for (int i = 0; i < connectedComponentList.size(); i++) {
			if (connectedComponentList.get(i).noPixels >= minArea) {

				if (connectedComponentList.get(i).bottom < originalBmp
						.getHeight()) {
					componentlist.add(connectedComponentList.get(i));
				} else {
					connectedComponentList.get(i).bottom = originalBmp
							.getHeight();
					componentlist.add(connectedComponentList.get(i));
				}
			}

		}

		System.out.println("Finnished drawing connected components.");
	}
	
	public byte[] compressImage(Bitmap image) {
		ByteArrayOutputStream stream = new ByteArrayOutputStream();
		image.compress(Bitmap.CompressFormat.PNG, 0, stream);
		byte[] bytes = stream.toByteArray();
		return bytes;
	}

	public void drawRectangles() {
		for (int i = 0; i < componentlist.size(); i++) {
			int top = componentlist.get(i).top;

			int bottom = componentlist.get(i).bottom;
			int left = componentlist.get(i).left;
			int right = componentlist.get(i).right;
			Core.rectangle(destImg, new Point(left, top), new Point(right,
					bottom), new Scalar(255, 0, 0), 2);

			int centerheight = (bottom + top) / 2;
			int centerwidth = (right + left) / 2;
			Point org = new Point(centerwidth, centerheight);
			Core.putText(destImg, "" + i, org, 3, 1, new Scalar(0, 0, 255), 5);

		}
		if (analysisorigin.equals("Protein")) {
			for (int j = 0; j < markerlist.size(); j++) {
				int top = markerlist.get(j).top;
				int bottom = markerlist.get(j).bottom;
				// int toptodisplay = 0;
				// int bottomtodisplay = 0;
				/*
				 * if(GaborActivity2.sigmavalue >= sigmatochange){ toptodisplay
				 * = top; bottomtodisplay = bottom; } else { toptodisplay = top
				 * - 12; bottomtodisplay = bottom - 12; }
				 */
				// 8/9
				// toptodisplay = top - 12;
				// bottomtodisplay = bottom - 12;

				int left = markerlist.get(j).left;
				int right = markerlist.get(j).right;
				Core.rectangle(destImg, new Point(left, top), new Point(right,
						bottom), new Scalar(255, 255, 0), 2);

				int centerheight = (bottom + top) / 2;
				Point org = new Point(right, centerheight);

				Core.putText(destImg, "" + j, org, 3, 1, new Scalar(0, 255, 0),
						5);

			}
		}

	}

	public void fixRectangles() {
		Mat srcImg = new Mat(grayBmp.getHeight(), grayBmp.getWidth(),
				CvType.CV_8U, new Scalar(4));
		Bitmap myBitmap32 = grayBmp.copy(Bitmap.Config.ARGB_8888, true);
		Utils.bitmapToMat(myBitmap32, srcImg);

		// get initial intensity average
		for (int i = 0; i < componentlist.size(); i++) {
			int averageFragmentIntensity = 0;
			int j = 0;
			int k = 0;

			for (j = 0; j + componentlist.get(i).left <= componentlist.get(i).right; j++) {
				for (k = 0; k + componentlist.get(i).top <= componentlist
						.get(i).bottom; k++) {
					// int intensity =
					// grayBmp.getPixel(componentlist.get(i).left + j,
					// componentlist.get(i).top + k);
					double[] intensity = srcImg.get(componentlist.get(i).top
							+ k, componentlist.get(i).left + j);
					averageFragmentIntensity += intensity[0];
				}
			}
			// test upwards first
			averageFragmentIntensity = averageFragmentIntensity
					/ ((componentlist.get(i).right - componentlist.get(i).left) * (componentlist
							.get(i).bottom - componentlist.get(i).top));
			upwardsTest(averageFragmentIntensity, componentlist.get(i), srcImg);
			Log.d("tag1",
					"component: " + i + " top: " + componentlist.get(i).top
							+ " bottom: " + componentlist.get(i).bottom);
			downwardsTest(averageFragmentIntensity, componentlist.get(i),
					srcImg);
		}
	}

	private void upwardsTest(int initialavg, ConnectedComponent cc, Mat srcImg) {
		boolean status = false;
		int initialtestavg = initialavg;

		while (status != true) {
			// initial moving up of one pixel
			cc.top -= 1;
			cc.bottom -= 1;
			int testavg = 0;
			int j = 0;
			int k = 0;
			for (j = 0; j + cc.left <= cc.right; j++) {

				for (k = 0; k + cc.top <= cc.bottom; k++) {
					if (k + cc.top > 0) {
						double[] intensity = srcImg
								.get(cc.top + k, cc.left + j);
						testavg += intensity[0];
					} else {
						status = true;
						break;
					}
				}

			}
			testavg = testavg / ((cc.right - cc.left) * (cc.bottom - cc.top));
			if (testavg <= initialtestavg) {
				initialtestavg = testavg;
				status = false;
			} else {
				status = true;
			}
		}
	}

	private void downwardsTest(int initialavg, ConnectedComponent cc, Mat srcImg) {
		boolean status = false;
		int initialtestavg = initialavg;

		while (status != true) {
			// initial moving up of one pixel
			cc.top += 1;
			cc.bottom += 1;
			int testavg = 0;
			int j = 0;
			int k = 0;

			for (j = 0; j + cc.left <= cc.right; j++) {
				for (k = 0; k + cc.top <= cc.bottom; k++) {
					if (k + cc.top <= srcImg.height()) {
						double[] intensity = srcImg
								.get(cc.top + k, cc.left + j);
						testavg += intensity[0];
					} else {
						status = true;
						break;
					}
				}

			}
			testavg = testavg / ((cc.right - cc.left) * (cc.bottom - cc.top));
			if (cc.bottom + 1 >= grayBmp.getHeight()) {
				status = true;
			} else {
				if (testavg <= initialtestavg) {
					initialtestavg = testavg;
					status = false;
				} else {
					status = true;
				}
			}
		}
	}

	
}
